<?php
/***************************************************************
*  Copyright notice
*  (c) 2009, jianyuzhu@gmail.com
*  All rights reserved
*  This script is part of the PPEMI project.
***************************************************************/

//
if( !defined('CONST_SESSION_LIFE_TIME') ) {
	define('CONST_SESSION_LIFE_TIME', 86400);//60 * 60 * 24 * 1
}

//
class CoreSessionBase extends Base {
	
	//constructor
	function CoreSessionBase($session_name = 'PPSID', $session_id = '') {
		parent::Base();
		
		//
		if( substr(SYS_RT_REQUEST_URI, 0, strlen('ws/admin')) == 'ws/admin' ) {
			$session_name .= 'A';
		} elseif( substr(SYS_RT_REQUEST_URI, 0, strlen('admin/')) == 'admin/' ) {
			$session_name .= 'A';
		} elseif( substr(SYS_RT_REQUEST_URI, 0, strlen('wsa.php')) == 'wsa.php' ) {
			$session_name .= 'A';
		} elseif( substr(SYS_RT_REQUEST_URI, 0, strlen('wsap.php')) == 'wsap.php' ) {
			$session_name .= 'A';
		}
		
		$this->session_name = $session_name;
		$this->session_id = $session_id;
	}
	
	function start() {
		global $request_ssl;
		global $cookie_domain, $cookie_path;
		
		session_set_save_handler(array($this, '_sess_open'), array($this, '_sess_close'), array($this, '_sess_read'), array($this, '_sess_write'), array($this, '_sess_destroy'), array($this, '_sess_gc'));
		
		//
		$this->_ip_address = '';
		$this->max_life_time = 1440;
		//
		$this->session_cookie_hash = false;
		$this->session_cookie_path = $cookie_path;
		$this->session_cookie_domain = $cookie_domain;
		$this->session_cookie_secure = 0;
		$this->session_table = $session_table;
		$this->session_data_table = $session_data_table;
		//$this->session_name = $session_name;
		
		$this->_session_name($this->session_name);
		$this->_session_save_path(CONFIG_SESSION_WRITE_DIRECTORY);
		
		//set the session cookie parameters
		if( function_exists('session_set_cookie_params') ) {
			session_set_cookie_params(0, $cookie_path, $cookie_domain);
		} elseif( function_exists('ini_set') ) {
			ini_set('session.cookie_lifetime', '0');
			ini_set('session.cookie_path', $cookie_path);
			ini_set('session.cookie_domain', $cookie_domain);
		}
		//
		if( isset($_POST[$this->session_name]) ) {
			$this->session_id = $this->_session_id($_POST[$this->session_name]);
		} elseif( ($request_ssl == 'SSL') && isset($_GET[$this->session_name]) ) {
			$this->session_id = $this->_session_id($_GET[$this->session_name]);
		} elseif( !empty($_COOKIE[$this->session_name]) ) {
			$this->session_id = $_COOKIE[$this->session_name];
		}
		//
		if( $this->session_cookie_hash == true && $this->session_id ) {
			$session_id_tmp = substr($this->session_id, 0, 32);
			if( $this->_session_key_hash($session_id_tmp) == substr($this->session_id, 32) ) {
				$this->session_id = $tmp_session_id;
			} else {
				$this->session_id = '';
			}
		}
		//
		if( !$this->session_id ) {
			$this->session_id = $this->_session_id();
			if( $this->session_cookie_hash == true ) {
				$session_id_cookie = $this->session_id . $this->_session_key_hash($this->session_id);
				setcookie($this->session_name, $session_id_cookie, 0, $this->session_cookie_path, $this->session_cookie_domain);
			} else {
				setcookie($this->session_name, $this->session_id, 0, $this->session_cookie_path, $this->session_cookie_domain);
			}
		}
		
		$this->_session_start();
	}
	
	function _sess_open($save_path, $session_name) {
		return true;
	}
	
	function _sess_close() {
		return true;
	}
	
	function _sess_read($key) {
		$query = "select value from pp_sessions where sesskey = '" . func_db_input($key) . "' and expiry > '" . time() . "'";
		$row = $this->adb->getRow($query);
		if( $row['value'] ) {
			return $row['value'];
		}
		return false;
	}
	
	function _sess_write($key, $val) {
		if( is_object($this->adb) ) {
			//
		} else {
			$this->adb = ADODBDatabase::getInstance();
			$this->adb->connect();
			$this->adb->query("SET NAMES 'utf8'");
		}
		
		$expiry = time() + CONST_SESSION_LIFE_TIME;
		$value = $val;
		
		$query = "select count(*) as total from pp_sessions where sesskey = '" . func_db_input($key) . "'";
		$row = $this->adb->getRow($query);
		
		if( $row['total'] > 0 ) {
			$this->adb->query("update pp_sessions set expiry = '" . func_db_input($expiry) . "', value = '" . func_db_input($value) . "' where sesskey = '" . func_db_input($key) . "'");
			return true;
		} else {
			$this->adb->query("insert into pp_sessions values ('" . func_db_input($key) . "', '" . func_db_input($expiry) . "', '" . func_db_input($value) . "')");
			return true;
		}
	}
	
	function _sess_destroy($key) {
		$this->adb->query("delete from pp_sessions where sesskey = '" . func_db_input($key) . "'");
		return true;
	}
	
	function _sess_gc($maxlifetime) {
		$this->adb->query("delete from pp_sessions where expiry < '" . time() . "'");
		
		return true;
	}
	
	//
	function _get_expiry() {
		return time() + $this->max_life_time;
	}
	
	//
	function _session_start() {
		return session_start();
	}
	
	function _session_startb() {
		if( get_cfg_var('session.auto_start') ) {
			return true;
		} else {
			return session_start();
		}
	}
	
	function _session_id($sessid = '') {
		if( !empty($sessid) ) {
			return session_id($sessid);
		} else {
			return session_id();
		}
	}
	
	function _session_name($name = '') {
		if( !empty($name) ) {
			return session_name($name);
		} else {
			return session_name();
		}
	}
	
	function _session_close() {
		if( PHP_VERSION >= '4.0.4' ) {
			return session_write_close();
		} elseif( function_exists('session_close') ) {
			return session_close();
		}
	}
	
	function _session_destroy() {
		return session_destroy();
	}
	
	function _session_save_path($path = '') {
		if( !empty($path) ) {
			return session_save_path($path);
		} else {
			return session_save_path();
		}
	}
	
	//
	function _session_key_hash($session_id) {
		$p = 'PPSESSION';
		
		return sprintf("%08x", crc32($session_id . $p));
	}
	
	//
	function get_session_id() {
		return $this->session_id;
	}
	
	function get_cookie() {
		return $this->session_name;
	}
	
	function generate_session_id() {
		$count = 10;
		$rand = 0;
		while($count--) {
			$rand = md5(uniqid(microtime(), 1));
			if( $rand != '' ) {
				$rand = md5($rand);
				$count = $this->adb->getCount("select count(*) as count from pp_sessions where sesskey = '" . $rand . "'");
				if( $count > 0 ) {
					return false;
				} else {
					break;
				}
			}
		}
		
		return $rand;
	}
	
	//
	function remember($username, $password) {
		$value = $this->_encrypt($username, $password);
		$up = strlen($password) . substr($value, 0, strlen($password)-1);
		setcookie("_un", $username, 0, $this->session_cookie_path, $this->session_cookie_domain);
		setcookie("_up", $up, 0, $this->session_cookie_path, $this->session_cookie_domain);
		setcookie("_unp", $value, 0, $this->session_cookie_path, $this->session_cookie_domain);
	}
	
	function rememberclean() {
		setcookie("_un", "", -1, $this->session_cookie_path, $this->session_cookie_domain);
		setcookie("_up", "", -1, $this->session_cookie_path, $this->session_cookie_domain);
		setcookie("_unp", "", -1, $this->session_cookie_path, $this->session_cookie_domain);
	}
	
	function checkcookie($un, $up, $unp) {
		if( substr($up, 0, 1) != strlen($up) ) {
			return false;
		}
		global $userObj;
		$password = $userObj->getUserPassword($un, 'users_email_address');
		$value = $this->_encrypt($un, $password);
		if( $un != $unp ) {
			return false;
		}
		if( $up != strlen($password) . substr($value, 0, strlen($password)-1) ) {
			return false;
		}
		
		return true;
	}
	
	//
	function setcookie($name, $value) {
		setcookie($name, $value, -1, $this->session_cookie_path, $this->session_cookie_domain);
	}
	
	function setcookie_userstatus() {
		$this->setcookie('_pustatus', ($_SESSION['suser']->userid > 0) ? 1 : 0);
	}
	
	//
	function clean($time = 1800) {
		$last = time() - $time;
		
		return $this->adb->delete("delete from pp_sessions where expiry <= '" . (int)$last . "'");
	}
	
	//
	function _encrypt($a, $b) {
		return substr(md5($a), 10, 20) . substr(md5($b), 10, 20);
	}
}
//
?>